/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { ArkFile, ImportInfo } from "arkanalyzer";
import { BaseChecker, BaseMetaData, Defects, FileMatcher, MatcherCallback, MatcherTypes, Rule } from "homecheck";

const gMetaData: BaseMetaData = {
  severity: 2,
  ruleDocPath: 'docs/xxxxx',
  description: "Avoid using import * to import specific symbols.",
}

export class ImportAllCheck implements BaseChecker {
  readonly metaData: BaseMetaData = gMetaData;
  public rule: Rule;
  public defects: Defects[] = [];

  private fileMatcher: FileMatcher = {
    matcherType: MatcherTypes.FILE,
  }

  public registerMatchers(): MatcherCallback[] {
    const matchFileCb: MatcherCallback = {
      matcher: this.fileMatcher,
      callback: this.check
    };
    return [matchFileCb];
  }

  public check = (arkFile: ArkFile): void => {
    for (const importInfo of arkFile.getImportInfos()) {
      let name = importInfo.getNameBeforeAs()
      if (name === '*') {
        this.addDefect(importInfo, arkFile);
      }
    }
  }

  private addDefect(info: ImportInfo, arkFile: ArkFile) {
    const severity = this.rule.alert ?? this.metaData.severity;
    const warnInfo = this.getWarnInfo(info, arkFile);
    const fixKey = warnInfo.line + '%' + warnInfo.startCol + '%' + warnInfo.endCol + '%' + this.rule.ruleId;
    const mergeKey = warnInfo.filePath + '%' + fixKey + '%' + this.metaData.description;
    this.defects.push(new Defects(
      warnInfo.line,
      warnInfo.startCol,
      this.metaData.description,
      severity,
      this.rule.ruleId,
      mergeKey,
      this.metaData.ruleDocPath,
      true,
      false,
      true,
      mergeKey
    ));
  }

  private getWarnInfo(info: ImportInfo, arkFile: ArkFile) {
    const originPositon = info.getOriginTsPosition();
    const line = originPositon.getLineNo();
    if (arkFile) {
      const startCol = originPositon.getLineNo();
      const endCol = startCol + 2;
      const originPath = arkFile.getFilePath();
      return {
        line,
        startCol,
        endCol,
        filePath: originPath
      }
    }
    return {
      line,
      startCol: 0,
      endCol: 0,
      filePath: ''
    }
  }
}